package com.cskaoyan.javase.oop1._12static._5exercise;

/**
 * 读程序题
 * 首先要找main方法
 * 启动main方法,触发Demo类的类加载
 * 这时就需要执行Demo类的static相关的内容
 * 主要是静态成员变量的显式赋值
 * 于是需要创建Cat类的对象
 * 于是类加载Demo过程中,连环触发Cat类的类加载
 *
 * 于是类加载Cat
 * Cat类的静态成员变量显式赋值需要创建Dog对象
 * 于是触发Dog类的类加载
 *
 * Dog类最后开始类加载,最先完成类加载
 * 并且Dog类没有static声明,不影响程序输出
 *
 * 类加载Dog完毕后,开始创建Dog对象
 * 目的是完成Cat类的类加载
 *
 * 于是创建Dog对象,找构造器
 * 程序的第一个输出是"dog"
 *
 * 创建Dog对象完毕后,Cat类的类加载就结束了
 * 于是开始创建Cat对象,目的是完成Demo类的类加载
 *
 * 于是找Cat类的构造器,程序的第二行输出是"cat"
 * 创建Cat对象完毕后,Demo类的类加载就结束了
 *
 * 以上过程的输出都是类加载过程中输出的!
 *
 * 于是开始启动main方法
 * 程序的第三行输出是"hello world!"
 *
 * 接下来main方法中需要创建Demo对象
 * 思考:
 *      还需不需考虑类加载呢?
 *  完全不需要,Demo,Dog,Cat三个类都已经完成类加载,不会再次类加载了,创建对象,直接找构造器执行就完事了!
 *
 * 但是注意Demo类的构造器应该在本类成员变量的显式赋值之后进行
 * 不会立刻执行
 * 所以程序应该先执行:
 * Dog dog = new Dog();
 * 于是程序输出"dog"
 * 最后输出"demo"
 *
 * @since 11:28
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    static Cat cat = new Cat();
    Dog dog = new Dog();
    Dog dog2;
    static Dog dog3;

    public static void main(String[] args) {
        System.out.println("hello world!");
        Demo d = new Demo();
    }

    public Demo() {
        System.out.println("demo");
    }
}

class Cat {
    static Dog dog = new Dog();

    public Cat() {
        System.out.println("cat");
    }
}

class Dog {
    /*
        这里就存在一个矛盾:
        Demo类的类加载还没有完全结束
        如何创建Demo类对象呢?
        代码块中再讲这个内容
     */
    static Demo demo = new Demo();

    public Dog() {
        System.out.println("dog");
    }
}